/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "MyTest"

#include <unistd.h>
#include <thread>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>

#include <gui/BufferQueue.h>

using namespace android;

struct DummyConsumer : public BnConsumerListener {
    void onDisconnect() override
    {
        printf("producer is disconnected.\n");
    }

    void onFrameAvailable(const BufferItem& item) override 
    {
        printf("onFrameAvailable: framenumber=%llu.\n", item.mFrameNumber);
    }

    void onBuffersReleased() override 
    {

    }

    void onSidebandStreamChanged() override 
    {

    }

};

// void consumer_process_thread(void *arg)
// {
//     sp<IGraphicBufferConsumer> consumer = ;
// }

sp<IGraphicBufferConsumer> consumer;

void consumer_process_thread()
{
    /****************** Consumer ***********************/
    while (1)
    {
        printf("#####################\n");
        BufferItem item;
        status_t status = consumer->acquireBuffer(&item, static_cast<nsecs_t>(0));
        //if (status == NO_ERROR)
        if (item.mGraphicBuffer != NULL)
        {
            //注意：每个slot第一次acquireBuffer时item.mGraphicBuffer不为空。
            //之后调用item.item.mAcquireCalled都会为true, 此时item.mGraphicBuffer为空，
            //需要应用自己做好保存mGraphicBuffer指针，以及维护好mGraphicBuffer与slot的对应关系。
            //参考ConsumerBase或GLConsumer的实现。
            //参考bq_producer_consumer_base3
            if (item.mGraphicBuffer == NULL)
                printf("##################1#mGraphicBuffer=NULL#\n");

            uint32_t* dataOut;
            item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
                            reinterpret_cast<void**>(&dataOut));
            printf("the data out is %d\n", *dataOut);
            item.mGraphicBuffer->unlock();

        }

        consumer->releaseBuffer(item.mSlot, item.mFrameNumber, EGL_NO_DISPLAY,
                EGL_NO_SYNC_KHR, Fence::NO_FENCE);

        usleep(1000000/2);
    }
}

int main(int argc, char** argv)
{
    sp<IGraphicBufferProducer> producer;
    //sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);

    consumer->consumerConnect(new DummyConsumer, false);

    sp<IServiceManager> serviceManager = defaultServiceManager();
    serviceManager->addService(String16("MyProducer"), IInterface::asBinder(producer));
    serviceManager->addService(String16("MyConsumer"), IInterface::asBinder(consumer));

    ProcessState::self()->startThreadPool();

    //std::thread consumer_th(consumer_process_thread, (void *)consumer);
    std::thread consumer_th(consumer_process_thread);

    IPCThreadState::self()->joinThreadPool();

    return 0;
}
